//
//  YLHealthKitManager.m
//  HealthKitManager
//
//  Created by JuneLee on 2018/11/9.
//

#import "YLHealthKitManager.h"
#import "YLHealthKitManager+Private.h"

typedef NS_ENUM(NSUInteger, YLAuthorizationStatus) {
    YLAuthorizationStatusNotDetermined = 0,
    YLAuthorizationStatusDenied = 1,
    YLAuthorizationStatusAuthorized = 2,
};

/** healthkit是否调用同步过历史数据方法记录的key */
#define kHealthKitSynchronizeDataKey @"kHealthKitSynchronizeDataKey"

API_AVAILABLE(ios(8.0))
@interface YLHealthKitManager ()

@property (nonatomic, strong) HKHealthStore *healthStore;
@end

@implementation YLHealthKitManager

static YLHealthKitManager *_healthManager = nil;
+ (YLHealthKitManager *)sharedManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _healthManager = [[YLHealthKitManager alloc] init];
    });
    return _healthManager;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _healthManager = [[super allocWithZone:zone] init];
    });
    return _healthManager;
}

- (instancetype)init {
    if (self = [super init]) {
        if (_healthStore == nil) {
            if (@available(iOS 8.0, *)) {
                _healthStore = [[HKHealthStore alloc] init];
            }
        }
    }
    return self;
}

#pragma mark - 判断是否支持
- (BOOL)isHealthKitAvailable {
    if (@available(iOS 8.0, *)) {
        return [HKHealthStore isHealthDataAvailable];
    }
    return NO;
}

#pragma mark - 请求权限
- (void)requestAuthorizationCompletion:(void (^)(BOOL, NSError * _Nonnull))block {
    BOOL authorization = [self isHealthKitAvailable];
    if (authorization) {
        NSMutableSet *shareSet = [self getSharedTypeFromPlist];
        NSMutableSet *readSet = [self getReadTypeFromPlist];
        if (shareSet.count && readSet.count) {
            [_healthStore requestAuthorizationToShareTypes:shareSet readTypes:readSet completion:^(BOOL success, NSError * _Nullable error) {
                block(success,error);
            }];
        }else {
            NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"请求权限的个数不能为空"                                                                      forKey:NSLocalizedDescriptionKey];
            NSError *error = [NSError errorWithDomain:@"com.yldHealthkit.Authorization" code:1024 userInfo:userInfo];
            block(NO,error);
        }
    }else {
        NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"手机系统低于8.0，不支持HealthKit"                                                                      forKey:NSLocalizedDescriptionKey];
        NSError *error = [NSError errorWithDomain:@"com.yldHealthkit.Authorization" code:1024 userInfo:userInfo];
        block(NO,error);
    }
}

#pragma mark - ---------------------------------写入---------------------------------
#pragma mark - 写入历史数据
- (void)writeHistoryData:(void (^)(YLHealthKitConfig * _Nonnull))dataConfigBlock completion:(void (^)(BOOL, NSError * _Nullable))block {
    YLHealthKitConfig *config = [[YLHealthKitConfig alloc] init];
    dataConfigBlock(config);
    
    NSString *userId = config.userId;
    NSString *value = [[NSUserDefaults standardUserDefaults] objectForKey:kHealthKitSynchronizeDataKey];
    if ([value containsString:userId]) {
        NSLog(@"已同步过历史数据到healthkit");
        return;
    }
    
    //先清除之前的
    [self clearHealthKitAllDataCompletion:^(BOOL success, NSError * _Nullable error) {
        if (success) {
            NSLog(@"历史数据清除成功");
        }
    }];
    
    if (config.healthArray.count <= 0) {
        //修改同步历史数据的标志位YES，下一次便不再同步
        [[NSUserDefaults standardUserDefaults] setValue:[NSString stringWithFormat:@"healthkit%@",userId] forKey:kHealthKitSynchronizeDataKey];
        [[NSUserDefaults standardUserDefaults] synchronize];
        block(YES,nil);
        return;
    }
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (int i = 0; i < config.healthArray.count; i ++) {
            YLHealthKitModel *model = config.healthArray[i];
            [self writeHealthKitData:model withCompletion:^(BOOL success, NSError * _Nullable error) {
                if (success) {
                    NSLog(@"第%d条 写入成功",i);
                    if (i == 0) {
                        //修改同步历史数据的标志位YES，下一次便不再同步
                        [[NSUserDefaults standardUserDefaults] setValue:[NSString stringWithFormat:@"healthkit%@",userId] forKey:kHealthKitSynchronizeDataKey];
                        [[NSUserDefaults standardUserDefaults] synchronize];
                    }
                }
                block(success,error);
            }];
        }
    });
}

#pragma mark - 写入（秤的数据：身高、体重、去脂体重、体脂率、bmi，bmr、心率）
- (void)writeHealthKitDataBlock:(void (^)(YLHealthKitModel * _Nonnull))healthKitDataBlock completion:(void (^)(BOOL, NSError * _Nullable))block{
    YLHealthKitModel *healthModel = [[YLHealthKitModel alloc] init];
    healthKitDataBlock(healthModel);
    if (healthModel == nil) {
        healthModel = [[YLHealthKitModel alloc] init];
    }

    [self writeHealthKitData:healthModel withCompletion:^(BOOL success, NSError * _Nullable error) {
        block(success,error);
    }];
}

#pragma mark -
- (void)writeHealthKitData:(YLHealthKitModel *)healthkitModel withCompletion:(void (^)(BOOL success, NSError *_Nullable error))block {
    if (@available(iOS 8.0, *)) {

        NSDate *date = healthkitModel.date;
        if (date == nil) {
            NSLog(@"------------保存的healthkit 模型的时间参数为nil------------");
            healthkitModel.date = [NSDate date];
        }
        __weak YLHealthKitManager *weakSelf = self;
        [self requestAuthorizationCompletion:^(BOOL success, NSError * _Nullable error) {
            if (success) {
                
                NSMutableArray *saveObject = [NSMutableArray array];
                if ([weakSelf authorizationStatusForType:(YLHealthKitTypeHeight)] == YLAuthorizationStatusAuthorized
                    && healthkitModel.height > 0) {
                    [saveObject addObject:[weakSelf sampleObject:healthkitModel healthKitType:(YLHealthKitTypeHeight)]];
                }
                
                if ([weakSelf authorizationStatusForType:(YLHealthKitTypeWeight)] == YLAuthorizationStatusAuthorized
                    && healthkitModel.weight > 0) {
                    [saveObject addObject:[weakSelf sampleObject:healthkitModel healthKitType:(YLHealthKitTypeWeight)]];
                }
                
                if ([weakSelf authorizationStatusForType:(YLHealthKitTypeFatWeight)] == YLAuthorizationStatusAuthorized
                    && healthkitModel.fatWeight > 0) {
                    [saveObject addObject:[weakSelf sampleObject:healthkitModel healthKitType:(YLHealthKitTypeFatWeight)]];
                }
                
                if ([weakSelf authorizationStatusForType:(YLHealthKitTypeBodyFat)] == YLAuthorizationStatusAuthorized
                    && healthkitModel.bodyFat > 0) {
                    [saveObject addObject:[weakSelf sampleObject:healthkitModel healthKitType:(YLHealthKitTypeBodyFat)]];
                }
                
                if ([weakSelf authorizationStatusForType:(YLHealthKitTypeBMI)] == YLAuthorizationStatusAuthorized
                    && healthkitModel.bmi > 0) {
                    [saveObject addObject:[weakSelf sampleObject:healthkitModel healthKitType:(YLHealthKitTypeBMI)]];
                }
                
                if (healthkitModel.heartRate > 0) {
                    [self saveBandData:(YLHealthKitTypeHeartRate) dataArray:[@[healthkitModel] mutableCopy] withCompletion:^(BOOL success, NSError * _Nullable error) {
                    }];
                }
                
                if ([weakSelf authorizationStatusForType:(YLHealthKitTypeBMR)] == YLAuthorizationStatusAuthorized
                    && healthkitModel.bmr > 0) {
                    //如果有bmr，要先删除原有的bmr，然后再保存
                    [weakSelf healthkitBMRHandle:healthkitModel saveObject:saveObject withCompletion:^(BOOL success, NSError * _Nullable error) {
                        block(success,error);
                    }];
                    return ;
                }
                
                //没有bmr，就直接保存
                [weakSelf saveHealthKitObjects:saveObject withCompletion:^(BOOL success, NSError * _Nullable error) {
                    block(success,error);
                }];
            }else {
                block(success,error);
            }
        }];
    }
}

#pragma mark - BMR的处理（先删除，在保存）
- (void)healthkitBMRHandle:(YLHealthKitModel *)model saveObject:(NSMutableArray *)saveObject withCompletion:(void (^)(BOOL success, NSError *_Nullable error))block{
    
    if (@available(iOS 8.0, *)) {
        
        [saveObject addObject:[self sampleObject:model healthKitType:(YLHealthKitTypeBMR)]];
        
        NSDate *currentDate = model.date;
        NSCalendar *calender = [NSCalendar currentCalendar];
        NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
        NSDateComponents *dateComponent = [calender components:unitFlags fromDate:currentDate];
        int hour = (int)[dateComponent hour];
        int minute = (int)[dateComponent minute];
        int second = (int)[dateComponent second];
        NSDate *nowDay = [model.date dateByAddingTimeInterval:  - (hour*3600 + minute * 60 + second)];
        NSDate *nextDay = [model.date dateByAddingTimeInterval:  - (hour*3600 + minute * 60 + second)  + 86400];
        
        NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:nowDay endDate:nextDay options:(HKQueryOptionNone)];
        HKQuantityType *bmrType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBasalEnergyBurned];
        __weak YLHealthKitManager *weakSelf = self;
        if (@available(iOS 9.0, *)) {
            [_healthStore deleteObjectsOfType:bmrType predicate:predicate withCompletion:^(BOOL success, NSUInteger deletedObjectCount, NSError * _Nullable error) {
                if (success && error == nil) {
                    [weakSelf saveHealthKitObjects:saveObject withCompletion:^(BOOL success, NSError * _Nullable error) {
                        block(success,error);
                    }];
                }else {
                    block(NO,error);
                }
            }];
        } else {
            [self deleteDayHealthKitDataToHKObjectType:[HKQuantityType class] typeIdentifier:HKQuantityTypeIdentifierBasalEnergyBurned startDate:[NSDate date] endDate:[NSDate date] isDeleteCurrentAppData:YES withCompletion:^(BOOL success, NSError * _Nullable error) {
                if (success && error == nil) {
                    [weakSelf saveHealthKitObjects:saveObject withCompletion:^(BOOL success, NSError * _Nullable error) {
                        block(success,error);
                    }];
                }else{
                    block(NO,error);
                }
            }];
        }
    }
}

#pragma mark - 写入步数、睡眠、心率
- (void)writeBandHealthKitData:(void (^)(NSMutableArray<YLHealthKitModel *> * _Nonnull, NSMutableArray<YLHealthKitModel *> * _Nonnull, NSMutableArray<YLHealthKitModel *> * _Nonnull))healthKitDataBlock completion:(void (^)(BOOL, NSError * _Nullable))block {
    
    NSMutableArray *stepArray = [NSMutableArray array];
    NSMutableArray *sleepArray = [NSMutableArray array];
    NSMutableArray *heartRateArray = [NSMutableArray array];
    healthKitDataBlock(stepArray,sleepArray,heartRateArray);

    __weak YLHealthKitManager *weakSelf = self;
    [self requestAuthorizationCompletion:^(BOOL success, NSError * _Nullable error) {
        if (success) {
            
            if (stepArray.count > 0) {//步数
                [weakSelf saveBandData:(YLHealthKitTypeStepCount) dataArray:stepArray withCompletion:^(BOOL success, NSError * _Nullable errore) {
                    block(success,error);
                }];
            }
            
            if (sleepArray.count > 0) {//睡眠
                [weakSelf saveBandData:(YLHealthKitTypeSleepAnalysis) dataArray:sleepArray withCompletion:^(BOOL success, NSError * _Nullable error) {
                    block(success,error);
                }];
            }
            
            if (heartRateArray.count > 0) {//心率
                [weakSelf saveBandData:(YLHealthKitTypeHeartRate) dataArray:heartRateArray withCompletion:^(BOOL success, NSError * _Nullable error) {
                    block(success,error);
                }];
            }
        }else {
            block(success,error);
        }
    }];
}

#pragma mark -
- (void)saveBandData:(YLHealthKitType)healthKitType dataArray:(NSMutableArray<YLHealthKitModel *> *)dataArray withCompletion:(void (^ _Nullable)(BOOL success, NSError *_Nullable error))block {
    if (@available(iOS 8.0, *)) {
        
        if ([self authorizationStatusForType:(healthKitType)] == YLAuthorizationStatusAuthorized) {
            NSDate *startDate = nil;
            NSDate *endDate = nil;
            NSMutableArray *saveObject = [NSMutableArray array];
            for (YLHealthKitModel *model in dataArray) {
                
                if (startDate == nil) startDate = model.startDate;
                if (endDate == nil) endDate = model.endDate;
                
                if ([model.startDate compare:startDate] == NSOrderedAscending) {
                    startDate = model.startDate;
                }
                if ([model.endDate compare:endDate] == NSOrderedDescending) {
                    endDate = model.endDate;
                }
                if (healthKitType == YLHealthKitTypeSleepAnalysis) {
                    [saveObject addObject:[self sleepSample:model]];
                }else {
                    [saveObject addObject:[self sampleObject:model healthKitType:(healthKitType)]];
                }
            }
            
            Class sampleType = [HKQuantityType class];
            if (healthKitType == YLHealthKitTypeSleepAnalysis) sampleType = [HKCategoryType class];
            HKQuantityTypeIdentifier identifier = [self getQuantityIdentifierWith:healthKitType];

            __weak YLHealthKitManager *weakSelf = self;
            [self deleteDayHealthKitDataToHKObjectType:sampleType typeIdentifier:identifier startDate:startDate endDate:endDate isDeleteCurrentAppData:YES withCompletion:^(BOOL success, NSError * _Nullable error) {
                if (success && error == nil) {
                    [weakSelf saveHealthKitObjects:saveObject withCompletion:^(BOOL success, NSError * _Nullable error) {
                        block(success,error);
                    }];
                }else {
                    block(NO,error);
                }
            }];
        } else {
            NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"无权限保存数据"                                                                      forKey:NSLocalizedDescriptionKey];
            NSError *error = [NSError errorWithDomain:@"com.yldHealthkit.Authorization" code:1024 userInfo:userInfo];
            block(NO,error);
        }
    }
}

#pragma mark - 保存
- (void)saveHealthKitObjects:(NSMutableArray *)saveObject withCompletion:(void (^ _Nullable)(BOOL success, NSError *_Nullable error))block{
    [self->_healthStore saveObjects:saveObject withCompletion:^(BOOL success, NSError * _Nullable error) {
        block(success,error);
    }];
}

#pragma mark - ---------------------------------删除---------------------------------
#pragma mark 删除第几天到第几天的数据(date可为一天中的任意数据)
- (void)deleteDayHealthKitDataToHKObjectType:(Class)sampleType typeIdentifier:(NSString *)typeIdentifier startDate:(NSDate *)startDate endDate:(NSDate *)endDate isDeleteCurrentAppData:(BOOL)isCurrentAppData withCompletion:(void (^ _Nullable)(BOOL success, NSError *_Nullable error))block{
    
    NSCalendar *calender = [NSCalendar currentCalendar];
    NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *startDateComponent = [calender components:unitFlags fromDate:startDate];
    int startDateHour = (int)[startDateComponent hour];
    int startDateMinute = (int)[startDateComponent minute];
    int startDateSecond = (int)[startDateComponent second];
    NSDate *deleteStartDate = [startDate dateByAddingTimeInterval:  - (startDateHour*3600 + startDateMinute * 60 + startDateSecond)];
    
    NSDateComponents *endDateComponent = [calender components:unitFlags fromDate:endDate];
    int endDateHour = (int)[endDateComponent hour];
    int endDateMinute = (int)[endDateComponent minute];
    int endDateSecond = (int)[endDateComponent second];
    NSDate *deleteEndDate = [startDate dateByAddingTimeInterval:  - (endDateHour*3600 + endDateMinute * 60 + endDateSecond) + 86400];
    
    [self deleteHealthKitDataToHKObjectType:sampleType typeIdentifier:typeIdentifier startDate:deleteStartDate endDate:deleteEndDate isDeleteCurrentAppData:isCurrentAppData withCompletion:^(BOOL success, NSError * _Nullable error) {
        block(success,error);
    }];
}

#pragma mark 删除指定date之间的healthkit数据
- (void)deleteHealthKitDataToHKObjectType:(Class)sampleType typeIdentifier:(NSString *)typeIdentifier startDate:(NSDate *)startDate endDate:(NSDate *)endDate isDeleteCurrentAppData:(BOOL)isCurrentAppData withCompletion:(void (^ _Nullable)(BOOL success, NSError *_Nullable error))block{
    
    __weak YLHealthKitManager *weakSelf = self;
    if (@available(iOS 8.0, *)) {
        [self getHealthKitDataToHKObjectType:sampleType typeIdentifier:typeIdentifier startDate:startDate endDate:endDate withCompletion:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
            
            if (error == nil) {
                if (results.count > 0) {
                    if (@available(iOS 9.0, *)) {
                        [weakSelf.healthStore deleteObjects:results withCompletion:^(BOOL success, NSError * _Nullable error) {
                            block(success,error);
                        }];
                    }else {
                        for (int i = 0; i < results.count; i ++) {
                            HKQuantitySample *quantitySample = results[i];
                            [weakSelf.healthStore deleteObject:quantitySample withCompletion:^(BOOL success, NSError * _Nullable error) {
                            }];
                        }
                    }
                }else {
                    block(YES,nil);
                }
            }else {
                block(NO,error);
            }
        }];
    }
}

/** 清除healthkit 所有数据 */
- (void)clearHealthKitAllDataCompletion:(void (^ _Nullable)(BOOL success, NSError *_Nullable error))block API_AVAILABLE(ios(8.0)){
    
    __weak YLHealthKitManager *weakSelf = self;
    [self requestAuthorizationCompletion:^(BOOL success, NSError * _Nullable error) {
        if (success) {
            HKQuantityType *bmiType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];
            HKQuantityType *bodyFatType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage];
            HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
            HKQuantityType *fatWeightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass];
            HKQuantityType *bmrType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBasalEnergyBurned];

            NSMutableArray *types = [NSMutableArray array];
            [types addObject:bmiType];
            [types addObject:bodyFatType];
            [types addObject:heightType];
            [types addObject:fatWeightType];
            [types addObject:bmrType];
            
            NSDate *startDate = [NSDate dateWithTimeIntervalSince1970:0];
            NSDate *endDate = [NSDate date];
            NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:(HKQueryOptionNone)];
            
            if (@available(iOS 9.0, *)) {
                for (HKQuantityType *type in types) {
                    [weakSelf.healthStore deleteObjectsOfType:type predicate:predicate withCompletion:^(BOOL success, NSUInteger deletedObjectCount, NSError * _Nullable error) {
                        block(success,error);
                    }];
                }
            }else {
                NSArray *identifiers = @[HKQuantityTypeIdentifierBodyMass,HKQuantityTypeIdentifierLeanBodyMass,HKQuantityTypeIdentifierBodyFatPercentage,HKQuantityTypeIdentifierBodyMassIndex,HKQuantityTypeIdentifierBasalEnergyBurned];
                for (NSString *identifier in identifiers) {
                    [weakSelf deleteDayHealthKitDataToHKObjectType:[HKQuantityType class] typeIdentifier:identifier startDate:startDate endDate:endDate isDeleteCurrentAppData:YES withCompletion:^(BOOL success, NSError * _Nullable error) {
                        block(success,error);
                    }];
                }
            }
        }else {
            block(success,error);
        }
    }];
}

#pragma mark - ---------------------------------获取---------------------------------
- (void)gethealthKitDataWithHealthKitType:(YLHealthKitType)healthKitType startDate:(NSDate *)startDate endDate:(NSDate *)endDate completion:(void (^)(NSArray<YLHealthKitModel *> * _Nullable, NSError * _Nullable))block API_AVAILABLE(ios(8.0)) {
    
    __weak YLHealthKitManager *weakSelf = self;
    [self requestAuthorizationCompletion:^(BOOL success, NSError * _Nullable error) {
        if (success) {
            if ([weakSelf authorizationStatusForType:(healthKitType)] == YLAuthorizationStatusAuthorized) {
                Class sampleType = [HKQuantityType class];
                if (healthKitType == YLHealthKitTypeSleepAnalysis) sampleType = [HKCategoryType class];
                HKQuantityTypeIdentifier identifier = [weakSelf getQuantityIdentifierWith:healthKitType];
                
                [weakSelf getHealthKitDataToHKObjectType:sampleType typeIdentifier:identifier startDate:startDate endDate:endDate withCompletion:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
                    
                    if (error) {
                        block(nil,error);
                    }else{
                        NSMutableArray *resultAll = [weakSelf handleSample:healthKitType results:results];
                        block(resultAll,error);
                    }
                }];
            }else {
                NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"无权限获取"                                                                      forKey:NSLocalizedDescriptionKey];
                NSError *error = [NSError errorWithDomain:@"com.yldHealthkit.Authorization" code:1024 userInfo:userInfo];
                block(nil,error);
            }
        }else {
            block(nil,error);
        }
    }];
}

/** 处理获取的数据 */
- (NSMutableArray *)handleSample:(YLHealthKitType)healthKitType results:(NSArray *)results API_AVAILABLE(ios(8.0)){
    
    NSMutableArray *resultsAll = [NSMutableArray array];
    for (int i = 0; i < results.count; i ++) {
        if (healthKitType == YLHealthKitTypeSleepAnalysis) {
            HKCategorySample *categorySample = results[i];
            YLHealthKitModel *sleep = [[YLHealthKitModel alloc] init];
            SleepType sleepType = SleepTypeInBed;
            if (categorySample.value == 0) {
                sleepType = SleepTypeInBed;
            }else if (categorySample.value == 1){
                sleepType = SleepTypeAsleep;
            }else if (categorySample.value == 2){
                sleepType = SleepTypeAwake;
            }
            sleep = [sleep initSleepType:sleepType startDate:categorySample.startDate endDate:categorySample.endDate];
            [resultsAll addObject:sleep];
        }else {
            HKQuantitySample *quantitySample = results[i];
            YLHealthKitModel *model = [[YLHealthKitModel alloc] init];
            
            model.startDate = quantitySample.startDate;
            model.endDate = quantitySample.endDate;
            if (healthKitType == YLHealthKitTypeStepCount) {
                model.step = [quantitySample.quantity doubleValueForUnit:[HKUnit countUnit]];
            }else if (healthKitType == YLHealthKitTypeHeartRate) {
                model.heartRate = [quantitySample.quantity doubleValueForUnit:[[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]]];
            }else {
                model.distance = [quantitySample.quantity doubleValueForUnit:[HKUnit meterUnitWithMetricPrefix:HKMetricPrefixKilo]]*1000;
            }
            [resultsAll addObject:model];
        }
    }
    return resultsAll;
}

#pragma mark - 向healthkit获取数据
- (void)getHealthKitDataToHKObjectType:(Class)sampleType typeIdentifier:(NSString *)typeIdentifier startDate:(NSDate *)startDate endDate:(NSDate *)endDate withCompletion:(void (^)(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error))block API_AVAILABLE(ios(8.0)){
    
    HKSampleType *samType = nil;
    if ([NSStringFromClass(sampleType) isEqualToString:@"HKQuantityType"]) {
        samType = [HKQuantityType quantityTypeForIdentifier:typeIdentifier];
    }else if ([NSStringFromClass(sampleType) isEqualToString:@"HKCategoryType"]){
        samType = [HKCategoryType categoryTypeForIdentifier:typeIdentifier];
    }
    if (samType) {
        
        NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];
        HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:samType predicate:predicate limit:0 sortDescriptors:nil resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
            
            NSString *identifier = [NSBundle mainBundle].infoDictionary[@"CFBundleIdentifier"];//筛选当前app的数据
            NSMutableArray *tempResult = [NSMutableArray array];
            for (int i = 0; i < results.count; i ++) {
                HKQuantitySample *quantitySample = results[i];
                NSString *boundleIdentifier = nil;
                if (@available(iOS 9.0, *)) {
                    boundleIdentifier = quantitySample.sourceRevision.source.bundleIdentifier;
                    if ([identifier isEqualToString:boundleIdentifier]) {
                        [tempResult addObject:quantitySample];
                    }
                } else {
                    boundleIdentifier = quantitySample.source.bundleIdentifier;
                    if ([identifier isEqualToString:boundleIdentifier]) {
                        [tempResult addObject:quantitySample];
                    }
                }
            }
            block(query,tempResult,error);
        }];
        [_healthStore executeQuery:query];
    }
}

#pragma mark - 判断某项指标是否有权限
- (YLAuthorizationStatus)authorizationStatusForType:(YLHealthKitType)type {
    if (@available(iOS 8.0, *)) {
        HKObjectType *objectType = nil;
        YLAuthorizationStatus status = YLAuthorizationStatusNotDetermined;
        switch (type) {
            case YLHealthKitTypeHeight:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
                break;
            case YLHealthKitTypeWeight:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
                break;
            case YLHealthKitTypeFatWeight:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass];
                break;
            case YLHealthKitTypeBodyFat:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage];
                break;
            case YLHealthKitTypeBMI:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];
                break;
            case YLHealthKitTypeBMR:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBasalEnergyBurned];
                break;
            case YLHealthKitTypeStepCount:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
                break;
            case YLHealthKitTypeHeartRate:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
                break;
            case YLHealthKitTypeSleepAnalysis:
                objectType = [HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis];
                break;
            case YLHealthKitTypeDistance:
                objectType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
                break;
            default: break;
        }
        if (objectType) {
            HKAuthorizationStatus authorizationStatus = [_healthStore authorizationStatusForType:objectType];
            switch (authorizationStatus) {
                case HKAuthorizationStatusNotDetermined:status = YLAuthorizationStatusNotDetermined; break;
                case HKAuthorizationStatusSharingDenied:status = YLAuthorizationStatusDenied;break;
                case HKAuthorizationStatusSharingAuthorized:status = YLAuthorizationStatusAuthorized;break;
                default:break;
            }
        }
        return status;
    }else {
        return YLAuthorizationStatusNotDetermined;
    }
}
@end

